/**
 * 
 */
package com.appspot.android2gather.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.appspot.android2gather.activity.ErrorMessage;
import com.appspot.android2gather.persistance.ActivityEntity;
import com.appspot.android2gather.persistance.PMF;
import com.beoui.geocell.GeocellManager;
import com.beoui.geocell.model.Point;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gson.Gson;
import static com.appspot.android2gather.activity.RequestParameters.*;

/**
 * @author Stefan Thaler
 */
public class ActivityManager
    extends HttpServlet
{

    /**
     * 
     */
    private static final long serialVersionUID = 2285855736378765578L;
    private static Gson gson = new Gson();

    /**
     * returns an Activity.
     */
    @Override 
    protected void doGet( HttpServletRequest req, HttpServletResponse resp )
        throws ServletException, IOException
    {
        if ( assigned( req.getParameter( "m" ) ) )
        {
            if ( req.getParameter( "m" ).equals( "post" ) )
            {
                doPost( req, resp );
                return;
            }
            if ( req.getParameter( "m" ).equals( "put" ) )
            {
                doPut( req, resp );
                return;
            }
            if ( req.getParameter( "m" ).equals( "delete" ) )
            {
                doDelete( req, resp );
                return;
            }
        }
        String id = req.getParameter( ID );

        if ( assigned( id ) )
        {
            PersistenceManager pm = PMF.get().getPersistenceManager();
            try
            {
                // em.getTransaction().begin();
                ActivityEntity activity = pm.getObjectById( ActivityEntity.class, Long.parseLong( id ) );
                String activityGson = gson.toJson( activity, ActivityEntity.class );
                resp.getWriter().write( activityGson );
                resp.flushBuffer();

            }
            catch (JDOObjectNotFoundException onfe) 
            {
                resp.getWriter().write( "null" );
                return;
            }
            finally
            {
                // em.getTransaction().commit();
                pm.close();
            }
        }
        else
        {
            String errorGson = gson.toJson( new ErrorMessage( "No id specified." ), ErrorMessage.class );
            resp.getWriter().write( errorGson );
            resp.flushBuffer();
        }

    }

    @Override
    /**
     * creates / updates an Activity.
     */
    protected void doPost( HttpServletRequest req, HttpServletResponse resp )
        throws ServletException, IOException
    {
        String id = req.getParameter( ID );

        if ( assigned( id ) )
        {
            updateActivity( req, resp, id );
        }
        else
        {
            createActivity( req, resp );
        }
    }

    protected void createActivity( HttpServletRequest req, HttpServletResponse resp )
        throws IOException
    {
        // validate parameters
        ArrayList<ErrorMessage> errors =
            checkParameters( req, NAME, CATEGORYLIST, DESCRIPTION, LATITUDE, LONGITUDE, STARTTIME, ENDTIME
                              );
        // some parameters are bad
        if ( errors.size() > 0 )
        {
            String message = gson.toJson( errors.toArray(), Object[].class );
            resp.getWriter().write( message );
            return;
        }

        // do the magic
        User creator = UserServiceFactory.getUserService().getCurrentUser();
       PersistenceManager pm = PMF.get().getPersistenceManager();
        try
        {
            ActivityEntity activity = new ActivityEntity();
            activity.setCreator( creator );
            activity.addAttendee( creator );

            activity.setLatitude( Double.parseDouble( req.getParameter( LATITUDE ) ) );
            activity.setLongitude( Double.parseDouble( req.getParameter( LONGITUDE ) ) );
            //activity.setAltitude( Double.parseDouble( req.getParameter( ALTITUDE ) ) );
            
            //todo move to client side
            Point p = new Point (Double.parseDouble( req.getParameter( LATITUDE ) ), Double.parseDouble( req.getParameter( LONGITUDE ) ));
            List<String> cells = GeocellManager.generateGeoCell(p); //get geocells in android phone
            //List<String> cells = new ArrayList<String>();
            activity.setGeocells( cells );

            activity.setStartTime( Long.parseLong( req.getParameter( STARTTIME ) ) );
            activity.setEndTime( Long.parseLong( req.getParameter( ENDTIME ) ) );
            
            activity.setDescription( req.getParameter( DESCRIPTION ) );
            activity.setName( req.getParameter( NAME ) );
            activity.setCategories(  req.getParameter( CATEGORYLIST )  );
            pm.makePersistent( activity );
           // String response = gson.toJson( new Boolean( true ), Boolean.class );
            //response += activity.getId();
            resp.getWriter().write( activity.getId()+"" );

        }
        finally
        {
            pm.close();
        }

    }

    public static ArrayList<ErrorMessage> checkParameters( HttpServletRequest req, String... namesToValidate )
    {
        ArrayList<ErrorMessage> errors = new ArrayList<ErrorMessage>();
        for ( String parameterName : namesToValidate )
        {
            if ( !assigned( req.getParameter( parameterName ) ) )
            {
                errors.add( new ErrorMessage( parameterName + " not specified." ) );
            }
        }
        return errors;
    }

    protected void updateActivity( HttpServletRequest req, HttpServletResponse resp, String id )
        throws IOException
    {
        User user = UserServiceFactory.getUserService().getCurrentUser();
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try
        {
            ActivityEntity activity = pm.getObjectById(  ActivityEntity.class, Long.parseLong( id ) );
            boolean requestorIsCreator = activity.getCreator().getEmail().equals( user.getEmail() );
            String response = "";

            if ( requestorIsCreator )
            {
                if ( assigned( req.getParameter( LATITUDE ) ) )
                    activity.setLatitude( Double.parseDouble( req.getParameter( LATITUDE ) ) );
                if ( assigned( req.getParameter( LONGITUDE ) ) )
                    activity.setLongitude( Double.parseDouble( req.getParameter( LONGITUDE ) ) );
                if ( assigned( req.getParameter( ALTITUDE ) ) )
                    activity.setAltitude( Double.parseDouble( req.getParameter( ALTITUDE ) ) );
                
                if ( assigned( "fbeid" ))
                    activity.setFacebookEventId(  req.getParameter( "fbeid" )  );

                if ( assigned( req.getParameter( STARTTIME ) ) )
                    activity.setStartTime( Long.parseLong( req.getParameter( STARTTIME ) ) );
                if ( assigned( req.getParameter( ENDTIME ) ) )
                    activity.setEndTime( Long.parseLong( req.getParameter( ENDTIME ) ) );

                if ( assigned( req.getParameter( DESCRIPTION ) ) )
                    activity.setDescription( req.getParameter( DESCRIPTION ) );
                if ( assigned( req.getParameter( NAME ) ) )
                    activity.setName( req.getParameter( NAME ) );
                if ( assigned( req.getParameter( CATEGORYLIST ) ) )
                    activity.setCategories( req.getParameter( CATEGORYLIST )  ); // update parameters
                response = gson.toJson( new Boolean( true ), Boolean.class );
                resp.getWriter().write( response );
            }
            else
            {
                response = gson.toJson( new ErrorMessage( "Operation not permitted." ), ErrorMessage.class );
            }
            resp.getWriter().write( response );
            resp.flushBuffer();

        }
        finally
        {
            pm.close();

        }

    }

    /**
     * removes an Activity.
     */
    @Override
    protected void doDelete( HttpServletRequest req, HttpServletResponse resp )
        throws ServletException, IOException
    {
        String id = req.getParameter( ID );
        User user = UserServiceFactory.getUserService().getCurrentUser();

        if ( assigned( id ) )
        {
            PersistenceManager pm = PMF.get().getPersistenceManager();
            try
            {
                ActivityEntity activity = pm.getObjectById( ActivityEntity.class, Long.parseLong( id ) );

                boolean requestorIsCreator = activity.getCreator().getEmail().equals( user.getEmail() );
                String response = "";

                if ( requestorIsCreator )
                {
                    pm.deletePersistent( activity );
                    response = gson.toJson( new Boolean( true ), Boolean.class );
                }
                else
                {
                    response = gson.toJson( new ErrorMessage( "Operation not permitted." ), ErrorMessage.class );
                }
                resp.getWriter().write( response );
                resp.flushBuffer();
            }
            finally
            {
                pm.close();
            }
        }
        else
        {
            String errorGson = gson.toJson( new ErrorMessage( "No id specified." ), ErrorMessage.class );
            resp.getWriter().write( errorGson );
            resp.flushBuffer();
        }
    }

}
